/************************************************************************
* ui.c
* voxelands - 3d voxel world sandbox game
* Copyright (C) Lisa 'darkrose' Milne 2016 <lisa@ltmnet.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program.  If not, see <http://www.gnu.org/licenses/>
************************************************************************/

#include "common.h"
#include "graphics.h"
#include "ui.h"

#include <stdarg.h>

/* TODO: ui scaling based off scale and autoscale settings */
static struct {
	widget_t *containers;
	widget_t *elements;
	material_t *logo;
	float scale;
	uint8_t autoscale;
	textbuffer_t loader;
} ui_data = {
	NULL,
	NULL,
	NULL,
	1.0,
	1
};

int ui_scale_setter(char* value)
{
	float v;
	if (!value)
		return 0;

	v = strtof(value,NULL);
	if (v < 0.0)
		return 0;

	ui_data.scale = v;

	return 0;
}
int ui_autoscale_setter(char* value)
{
	ui_data.autoscale = parse_bool(value);

	return 0;
}

/* find an empty container, or create a new one */
widget_t *ui_widget_container()
{
	widget_t *w = ui_data.containers;

	while (w) {
		if (!w->style.visible && !w->child && !w->x)
			return w;
		w = w->next;
	}
/*
	w = ui_widget_create(UI_WIDGET_CONTAINER,NULL);
*/
	return w;
}

/* initialise the ui */
int ui_init()
{
	font_t *f;
	char* fontname = "font.ttf";

	if (config_get_bool("ui.font.unifont"))
		fontname = "unifont.ttf";

	font_load(fontname,"default");

	ui_data.logo = mat_from_image("texture","logo.png");
	mat_options(ui_data.logo,MATOPT_ALPHA_BLEND);

	f = font_find("default");

	textbuffer_init(&ui_data.loader,f,16,0,350,0,0,0,TB_OPT_NONE);

	return 0;
}

/* draw the ui */
void ui_render()
{
	widget_t *w;
	widget_t *wc;
	int mouse[2];
	int pos[2];
	int size[2];
	int bx;
	int by;
	int bw;
	int bh;

	w = ui_data.containers;
	while (w) {
		/* TODO: uncomment this
		if (w->style.visible)
			ui_widget_draw(w); */
		w = w->next;
	}

	wc = ui_data.containers;
	while (wc) {
		if (wc->style.visible) {
			w = wc->child;
			while (w) {
				if (w->hover && w->parent && w->parent->hover && w->htext.length) {
					events_get_mouse(pos);
					textbuffer_get_dimensions(&w->htext,size);
					mouse[0] = pos[0];
					mouse[1] = pos[1];
					pos[0] += 10;
					if (mouse[1] > w->style.ttfont_size) {
						pos[1] -= w->style.ttfont_size;
						if (mouse[0] > (wm_data.size.width-size[0]))
							pos[0] -= size[0]+10;
					}else{
						pos[0] -= size[0]+10;
					}

					bx = pos[0]-1;
					by = pos[1];
					bw = size[0]+2;
					bh = size[1];
/*
					if (w->style.has_ttbg)
						draw2d_rect(&w->style.ttbg,bx,by,bw,bh);

					if (w->style.has_ttborder) {
						draw2d_line(&w->style.ttborder,bx,by,bx+bw,by);
						draw2d_line(&w->style.ttborder,bx,by,bx,by+bh );
						draw2d_line(&w->style.ttborder,bx+bw,by,bx+bw,by+bh);
						draw2d_line(&w->style.ttborder,bx,by+bh,bx+bw,by+bh);
					}
*/

					w->htext.x = pos[0];
					w->htext.y = pos[1];
					render2d_textbuffer(&w->htext);
				}
				w = w->next;
			}
		}
		wc = wc->next;
	}
}

/* event handler for the msgbox */
static int ui_msg_event(widget_t *w)
{
	msgbox_data_t *wd = &w->parent->data->msg;
	if (w->id == wd->btn1->id) {
		if (wd->btn1_func)
			wd->btn1_func(w);
	}else if (w->id == wd->btn2->id) {
		if (wd->btn2_func)
			wd->btn2_func(w);
	}else{
		return EVENT_UNHANDLED;
	}
/*
	ui_widget_free(w->parent);
*/
	return EVENT_HANDLED;
}

/* the default loading screen */
void ui_loader(char* str)
{
	render_pre();
	textbuffer_clear(&ui_data.loader);
	textbuffer_addstr(&ui_data.loader,str);
	ui_data.loader.x = (wm_data.size.width/2)-(ui_data.loader.cw/2);
	render2d_textbuffer(&ui_data.loader);
	render2d_quad_mat(ui_data.logo,412,150,200,200);
	render_post();
}

/* create a popup message box */
void ui_msg(uint8_t type, char* txt, int (*func)(), ...)
{
	va_list ap;
	widget_t *con;

	if (!(type == UIMSG_OC || type == UIMSG_OK || type == UIMSG_YN) || !txt) {
		vlprintf(CN_WARN, "Invalid message type: %d",type);
		return;
	}

	con = ui_widget_container();

	con->style.w = 300;
	con->style.h = 120;
	con->style.x = UI_ALIGN_CENTRE;
	con->style.y = UI_ALIGN_MIDDLE;

	con->style.visible = 1;
	con->data = malloc(sizeof(widget_data_t));
	con->data->msg.container = con;
	con->data->msg.btn1_func = func;
	con->data->msg.btn2_func = NULL;
/*
	con->data->msg.txt = ui_widget_create(UI_WIDGET_LABEL,con);
*/	con->data->msg.txt->style.w = 300;
	con->data->msg.txt->style.x = 0;
	con->data->msg.txt->style.text_align = UI_ALIGN_CENTRE;
	con->data->msg.txt->style.y = 20;
/*
	ui_widget_value(con->data->msg.txt,txt);
*/
/*	con->data->msg.btn1 = ui_widget_create(UI_WIDGET_BUTTON,con);
*/	con->data->msg.btn1->events->mclick = &ui_msg_event;

/*	con->data->msg.btn2 = ui_widget_create(UI_WIDGET_BUTTON,con);
*/	con->data->msg.btn2->events->mclick = &ui_msg_event;

	con->data->msg.btn1->style.x = 290-con->data->msg.btn1->style.w;
	con->data->msg.btn1->style.y = 65;
	con->data->msg.btn2->style.x = con->data->msg.btn1->style.x-10-con->data->msg.btn2->style.w;
	con->data->msg.btn2->style.y = 65;

	if (type == UIMSG_OC) {
		va_start(ap,func);
		*(void**)(&con->data->msg.btn2_func) = va_arg(ap,int (*));
		va_end(ap);
/*		ui_widget_value(con->data->msg.btn1,"OK");
		ui_widget_value(con->data->msg.btn2,"Cancel");
*/	}else if (type == UIMSG_OK) {
		con->data->msg.btn2->style.visible = 0;
/*		ui_widget_value(con->data->msg.btn1,"OK");
*/	}else if (type == UIMSG_YN) {
		va_start(ap,func);
		*(void**)(&con->data->msg.btn2_func) = va_arg(ap,int (*));
		va_end(ap);
/*		ui_widget_value(con->data->msg.btn1,"Yes");
		ui_widget_value(con->data->msg.btn2,"No");
*/	}
}

/* event handler for the optbox */
static int ui_opt_event(widget_t *w)
{
	optbox_data_t *wd = &w->parent->data->opb;
	optbox_btn_t *btn = wd->buttons;

	while (btn) {
		if (btn->btn->id == w->id)
			break;
		btn = btn->next;
	}

	if (!btn) {
		return EVENT_UNHANDLED;
	}

	btn->func(w);
/*
	ui_widget_free(w->parent);
*/
	return EVENT_HANDLED;
}

/* create an option select popup box */
void ui_opt(char* txt, ...)
{
	va_list ap;
	widget_t *con;
	int (*f)(widget_t*);
	char* t;
	optbox_btn_t *b;
	int y = 95;

	if (!txt || !txt[0])
		return;
	va_start(ap,txt);
	t = (char*)va_arg(ap,char*);
	if (!t)
		return;
	*(void**)(&f) = va_arg(ap,int (*));
	if (!f)
		return;

	con = ui_widget_container();
	con->data = malloc(sizeof(widget_data_t));
	con->style.w = 200;
	con->style.x = UI_ALIGN_CENTRE;
	con->style.y = UI_ALIGN_MIDDLE;
	con->style.visible = 1;

	con->data->opb.container = con;
/*	con->data->opb.txt = ui_widget_create(UI_WIDGET_LABEL,con);
	con->data->opb.txt->style.x = 100-((print_length(1,SML_FONT,txt))/2);
*/	if (con->data->opb.txt->style.x < 0)
		con->data->opb.txt->style.x = 0;
	con->data->msg.txt->style.y = 20;
/*	ui_widget_value(con->data->opb.txt,txt);
*/
	con->data->opb.buttons = malloc(sizeof(optbox_btn_t));
	con->data->opb.buttons->func = f;
/*	con->data->opb.buttons->btn = ui_widget_create(UI_WIDGET_BUTTON,con);
*/	con->data->opb.buttons->btn->style.x = 63;
	con->data->opb.buttons->btn->style.y = 65;
	con->data->opb.buttons->btn->events->mclick = &ui_opt_event;
/*	ui_widget_value(con->data->opb.buttons->btn,t);
*/	b = con->data->opb.buttons;

	con->data->opb.buttons->next = NULL;

	while ((t = (char*)va_arg(ap,char*)) != NULL && (*(void**)(&f) = va_arg(ap,int (*))) != NULL) {
		b->next = malloc(sizeof(optbox_btn_t));
		b->next->func = f;
/*		b->next->btn = ui_widget_create(UI_WIDGET_BUTTON,con);
*/		b->next->btn->style.x = 63;
		b->next->btn->style.y = y;
		b->next->btn->events->mclick = &ui_opt_event;
/*		ui_widget_value(b->next->btn,t);
*/		b = b->next;
		b->next = NULL;
		y += 30;
	}

	va_end(ap);
	con->style.h = y;
}
